package com.niiwoo.civet.trade.service.local.intelligenceInvest;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.niiwoo.activity.stage.dto.request.prize.SummarizePrizeAmountReqDTO;
import com.niiwoo.activity.stage.dto.response.prize.InvestorExtraDetailDTO;
import com.niiwoo.activity.stage.dto.response.prize.SummarizeAmountRespDTO;
import com.niiwoo.activity.stage.enums.prize.UserPrizeTypeIdEnum;
import com.niiwoo.activity.stage.service.prize.ActivityPrizeDubboService;
import com.niiwoo.civet.account.dto.request.StatisticUserBillAmountRequestDTO;
import com.niiwoo.civet.account.dto.response.StatisticUserBillAmountReponseDTO;
import com.niiwoo.civet.account.enums.BillAmountStatisticsEnum;
import com.niiwoo.civet.account.service.bill.UserBillStatisticsDubboService;
import com.niiwoo.civet.trade.dao.entity.*;
import com.niiwoo.civet.trade.dao.mapper.*;
import com.niiwoo.civet.trade.dto.IntelligenceUnfreezeDTO;
import com.niiwoo.civet.trade.dto.ProjectInvestOrderListDTO;
import com.niiwoo.civet.trade.dto.invest.FullProjectDueInPrincipalAndInterestDTO;
import com.niiwoo.civet.trade.dto.invest.IntelligenceInvestOrderMaxAndMinDateDTO;
import com.niiwoo.civet.trade.dto.request.IntelligenceInvestDubboRequest;
import com.niiwoo.civet.trade.dto.request.ProjectInvestOrderPageRequest;
import com.niiwoo.civet.trade.dto.request.intelligenceInvest.IntelligenceDetailListRequestDTO;
import com.niiwoo.civet.trade.dto.request.intelligenceInvest.IntelligenceOrderDetailRequestDTO;
import com.niiwoo.civet.trade.dto.request.intelligenceInvest.IntelligenceOrderListRequestDTO;
import com.niiwoo.civet.trade.dto.response.InvestOrderMaxandMinDateResponseDTO;
import com.niiwoo.civet.trade.dto.response.intelligenceInvest.IntelligenceDetailListResponseDTO;
import com.niiwoo.civet.trade.dto.response.intelligenceInvest.IntelligenceInvestOrderDTO;
import com.niiwoo.civet.trade.dto.response.intelligenceInvest.IntelligenceOrderDetailResponseDTO;
import com.niiwoo.civet.trade.dto.response.intelligenceInvest.ProjectPackageInvestOrderDTO;
import com.niiwoo.civet.trade.enums.*;
import com.niiwoo.civet.trade.service.local.invest.InvestOrderService;
import com.niiwoo.civet.user.dto.request.SimpleOrgInfo;
import com.niiwoo.civet.user.dto.response.UserBasicInfoDTO;
import com.niiwoo.civet.user.service.OrganizationDubboService;
import com.niiwoo.civet.user.service.UserBasicInfoDubboService;
import com.niiwoo.tripod.base.plan.RepaymentPlanContext;
import com.niiwoo.tripod.base.plan.support.PeriodUnitEnum;
import com.niiwoo.tripod.base.plan.support.RepaymentPlanDTO;
import com.niiwoo.tripod.provider.dto.response.PageResponseDTO;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

import static org.springframework.transaction.annotation.Isolation.READ_COMMITTED;

@Slf4j
@Service
public class IntelligenceOrderService {

	@Reference(version = "1.0.0")
	private ActivityPrizeDubboService activityPrizeDubboService;
	@Reference(version = "1.0.0")
	private OrganizationDubboService organizationDubboService;
	@Reference(version = "1.0.0")
	private UserBasicInfoDubboService userBasicInfoDubboService;

	@Autowired
	private InvestOrderService investOrderService;
	@Autowired
	private SnowflakeIdWorker snowflakeIdWorker;
	@Autowired
	private ProjectMapperExt projectMapperExt;
	@Autowired
	private InvestorCreditorMapperExt investorCreditorMapperExt;
	@Autowired
	private ProjectInvestOrderMapperExt projectInvestOrderMapper;
	@Autowired
	private ProjectPackageInvestOrderMapperExt projectPackageInvestOrderMapperExt;
	@Autowired
	private ProjectPackageInvestOrderDetailMapperExt projectPackageInvestOrderDetailMapperExt;
	@Autowired
	private InvestAmountUnfreezeMapper investAmountUnfreezeMapper;
	@Autowired
	private ProjectInvestorPlanMapperExt projectInvestorPlanMapper;

	@Reference(version = "1.0.0")
	private UserBillStatisticsDubboService userBillStatisticsDubboService;

	/**
	 * 智能投包订单列表
	 *
	 * @param requestDTO
	 *            请求DTO
	 * @return IntelligenceOrderListResponseDTO
	 */
	public PageResponseDTO<IntelligenceInvestOrderDTO> intelligenceOrderList(IntelligenceOrderListRequestDTO requestDTO) {
		log.info("intelligenceOrderList requestDTO:{}", JSON.toJSON(requestDTO));
		PageResponseDTO<IntelligenceInvestOrderDTO> pageResponseDTO = new PageResponseDTO<>();
		Integer count = projectPackageInvestOrderMapperExt.getIntelligenceInvestOrderCount(requestDTO);
		if (count <= 0) {
			pageResponseDTO.setTotalCount(count);
			pageResponseDTO.setItems(new ArrayList<>());
			pageResponseDTO.measureTotalPage(count, requestDTO.getPageSize());
			return pageResponseDTO;
		}

		List<IntelligenceInvestOrderDTO> list = new ArrayList<>();
		List<ProjectPackageInvestOrder> intelligenceInvestOrderList = projectPackageInvestOrderMapperExt.getIntelligenceInvestOrderList(requestDTO);
		for (ProjectPackageInvestOrder packageInvestOrder : intelligenceInvestOrderList) {
			IntelligenceInvestOrderDTO investOrder = new IntelligenceInvestOrderDTO();
			investOrder.setPackageType(packageInvestOrder.getPackageType());
			investOrder.setPackageInvestOrderId(packageInvestOrder.getId());
			investOrder.setTitle(packageInvestOrder.getTitle());
			investOrder.setDeadline(packageInvestOrder.getDeadline());
			investOrder.setDeadlineUnit(packageInvestOrder.getDeadlineUnit());
			investOrder.setBorrowRate(packageInvestOrder.getBorrowRate());
			investOrder.setAddRate(packageInvestOrder.getActivityRaiseRate());
			investOrder.setStatus(packageInvestOrder.getEvolutionStatus());
			investOrder.setAmount(PackageInvestOrderEvolutionStatusEnum.CLOSED.getValue().equals(packageInvestOrder.getEvolutionStatus()) ? packageInvestOrder.getAmount() : packageInvestOrder.getRealInvestAmount());

			// 包投资订单衍生状态(0处理中，1投资中，2回款中，3回款逾期，4已关闭，5已结清)
			if (PackageInvestOrderEvolutionStatusEnum.CLOSED.getValue().equals(packageInvestOrder.getEvolutionStatus())
					|| PackageInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(packageInvestOrder.getEvolutionStatus())) {
				investOrder.setTime(packageInvestOrder.getUpdateTime());
			} else {
				investOrder.setTime(packageInvestOrder.getCreateTime());
			}

			Set<Long> investOrderIds = new HashSet<>();
			List<ProjectPackageInvestOrderDetail> investOrderDetailList = projectPackageInvestOrderDetailMapperExt.selectByPackageInvestOrderId(packageInvestOrder.getId());
			investOrderDetailList.forEach(investOrderDetail -> investOrderIds.add(investOrderDetail.getInvestOrderId()));

			// 对应包订单状态的标的个数
			if(packageInvestOrder.getProjectNum() > 1 && investOrderIds.size() > 0){
				List<ProjectInvestOrder> projectInvestOrderList = projectInvestOrderMapper.selectByInvestOrderIds(investOrderIds);
				projectInvestOrderList.forEach( projectInvestOrder -> {
					if(packageInvestOrder.getEvolutionStatus().equals(projectInvestOrder.getEvolutionStatus())){
						investOrder.setIntelligenceCount(investOrder.getIntelligenceCount() + 1);
					}
				});
			}else {
				investOrder.setIntelligenceCount(packageInvestOrder.getProjectNum());
			}

			// 实际收益=实收利息+实收加息
			if (PackageInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(packageInvestOrder.getEvolutionStatus())) {
				IntelligenceOrderDetailRequestDTO intelligenceOrderDetailRequestDTO = new IntelligenceOrderDetailRequestDTO();
				intelligenceOrderDetailRequestDTO.setPackageInvestOrderId(packageInvestOrder.getId());
				intelligenceOrderDetailRequestDTO.setUserId(requestDTO.getUserId());
				investOrder.setInterest(this.intelligenceOrderDetail(intelligenceOrderDetailRequestDTO).getReferenceIncome());
			} else {
				// 参考收益=参考利息+参考加息
				investOrder.setInterest(packageInvestOrder.getInterest().add(packageInvestOrder.getAddInterest()));
			}
			list.add(investOrder);
		}

		pageResponseDTO.setItems(list);
		pageResponseDTO.setTotalCount(count);
		pageResponseDTO.measureTotalPage(count, requestDTO.getPageSize());
		return pageResponseDTO;
	}

	/**
	 * 智能投包订单详情
	 *
	 * @param requestDTO
	 *            请求DTO
	 * @return IntelligenceOrderDetailResponseDTO
	 */
	public IntelligenceOrderDetailResponseDTO intelligenceOrderDetail(IntelligenceOrderDetailRequestDTO requestDTO) {
		log.info("intelligenceOrderDetail IntelligenceOrderDetailsRequestDTO:{}", JSON.toJSONString(requestDTO));
		IntelligenceOrderDetailResponseDTO responseDTO = null;
		ProjectPackageInvestOrder packageInvestOrder = projectPackageInvestOrderMapperExt.selectByPrimaryKey(requestDTO.getPackageInvestOrderId());
		if (packageInvestOrder != null) {
			responseDTO = new IntelligenceOrderDetailResponseDTO();
			responseDTO.setPackageType(packageInvestOrder.getPackageType());
			responseDTO.setPackageInvestOrderId(packageInvestOrder.getId());
			responseDTO.setPackageId(packageInvestOrder.getPackageId());
			responseDTO.setTitle(packageInvestOrder.getTitle());
			responseDTO.setDeadline(packageInvestOrder.getDeadline());
			responseDTO.setDeadlineUnit(packageInvestOrder.getDeadlineUnit());
			responseDTO.setBorrowRate(packageInvestOrder.getBorrowRate());
			responseDTO.setAddRate(packageInvestOrder.getActivityRaiseRate());
			responseDTO.setStatus(packageInvestOrder.getEvolutionStatus());
			responseDTO.setAmount(PackageInvestOrderEvolutionStatusEnum.CLOSED.getValue().equals(packageInvestOrder.getEvolutionStatus()) ? packageInvestOrder.getAmount() : packageInvestOrder.getRealInvestAmount());
			responseDTO.setIntelligenceCount(packageInvestOrder.getProjectNum());
			responseDTO.setRepaymentType(packageInvestOrder.getRepaymentType());
			responseDTO.setPrize(packageInvestOrder.getPrizeName());
			responseDTO.setSubmitTime(packageInvestOrder.getCreateTime());
			responseDTO.setEndTime(packageInvestOrder.getCloseTime());
			responseDTO.setMessage(packageInvestOrder.getCloseReason() != null ? InvestOrderCloseReasonEnum.enumOf(packageInvestOrder.getCloseReason()).getDesc() : "");
			if (PackageInvestOrderEvolutionStatusEnum.CLOSED.getValue().equals(packageInvestOrder.getEvolutionStatus())){
				responseDTO.setTotalRepayPriInter(packageInvestOrder.getRealInvestAmount().add(packageInvestOrder.getInterest()).add(packageInvestOrder.getAddInterest()));
			}

			Set<Long> investOrderIds = new HashSet<>();
			List<ProjectPackageInvestOrderDetail> investOrderDetailList = projectPackageInvestOrderDetailMapperExt.selectByPackageInvestOrderId(packageInvestOrder.getId());
			investOrderDetailList.forEach(investOrderDetail -> investOrderIds.add(investOrderDetail.getInvestOrderId()));

			BigDecimal investInterest = BigDecimal.ZERO;
			if(investOrderIds.size() > 0) {
				BigDecimal totalRepayPriInter = BigDecimal.ZERO;
				List<InvestorCreditor> investorCreditorList = investorCreditorMapperExt.selectByInvestOrderIds(investOrderIds);

				for (InvestorCreditor investorCreditor : investorCreditorList) {
                    // 已回金额:统计该订单所有标的已回款的总金额(已回本金+已回利息+已回罚息+已回标的加息)
                    responseDTO.setRepayAmount(responseDTO.getRepayAmount().add(investorCreditor.getReceivedCapital()).add(investorCreditor.getReceivedInterest()).add(investorCreditor.getReceivedPenaltyFee()));

                    if (PackageInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(packageInvestOrder.getEvolutionStatus())) {
                        if (responseDTO.getRepayTime() == null) {
                            responseDTO.setRepayTime(investorCreditor.getOverTime());
                        } else if (responseDTO.getRepayTime() != null && responseDTO.getRepayTime().before(investorCreditor.getOverTime())) {
                            responseDTO.setRepayTime(investorCreditor.getOverTime());
                        }
                        responseDTO.setEndTime(responseDTO.getRepayTime());
                    }

					// 待收本息 = 待收本金 + 待收利息(本金+利息+带收加息-已收本金-已收利息)
					if ( PackageInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(packageInvestOrder.getEvolutionStatus())) {
						totalRepayPriInter = totalRepayPriInter.add(investorCreditor.getReceivedCapital().add(investorCreditor.getReceivedInterest()).add(investorCreditor.getReceivedPenaltyFee()));
					}else {
						if(!InvestorCreditorStatusEnum.FINISH.getStatus().equals(investorCreditor.getStatus()) &&
								!InvestorCreditorStatusEnum.TRANSFERRED.getStatus().equals(investorCreditor.getStatus())) {
							totalRepayPriInter = totalRepayPriInter.add(investorCreditor.getCapital()).add(investorCreditor.getInterest())
									.subtract(investorCreditor.getReceivedCapital()).subtract(investorCreditor.getReceivedInterest());
						}
					}
				}
				// 包订单为回款中，回款逾期中取实际待收本息 (处理中与投资中，取单个待满标的待收本息)
				if (PackageInvestOrderEvolutionStatusEnum.BACKING.getValue().equals(packageInvestOrder.getEvolutionStatus())
						|| PackageInvestOrderEvolutionStatusEnum.BACKING_OVERDUE.getValue().equals(packageInvestOrder.getEvolutionStatus())
						|| PackageInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(packageInvestOrder.getEvolutionStatus())) {
					responseDTO.setTotalRepayPriInter(totalRepayPriInter);
				}else if(PackageInvestOrderEvolutionStatusEnum.DEALING.getValue().equals(packageInvestOrder.getEvolutionStatus())
						|| PackageInvestOrderEvolutionStatusEnum.INVESTING.getValue().equals(packageInvestOrder.getEvolutionStatus())){
					BigDecimal toAddInterest = BigDecimal.ZERO;
					List<FullProjectDueInPrincipalAndInterestDTO> list = projectInvestorPlanMapper.selectIntelligenceFullProjectDueInPrincipalAndInterest(investOrderIds);
					for(FullProjectDueInPrincipalAndInterestDTO dto : list){
						responseDTO.setTotalRepayPriInter(responseDTO.getTotalRepayPriInter().add(dto.getDueInPrincipalAndInterest()));
						// 标加息
						if(dto.getActivityRaiseRate() != null && dto.getActivityRaiseRate().compareTo(BigDecimal.ZERO) > 0){
							toAddInterest = toAddInterest.add(this.getProjectActivityCurrentPeriodAddInterest(dto.getActivityRaiseRate(), dto.getInvestOrderId(), Byte.valueOf("0")));
						}
						// 加息劵
						if(dto.getPrizeId() != null && UserPrizeTypeIdEnum.INVESTMENT_RAISE_INTEREST_RATES.getPrizeType().equals(dto.getPrizeTypeId())){
							toAddInterest = toAddInterest.add(this.getPrizeCurrentPeriodAddInterest(dto.getInvestOrderId(), dto.getProjectId(), Byte.valueOf("0")));
						}
						// 包加息
						if(packageInvestOrder.getActivityRaiseRate() != null && packageInvestOrder.getActivityRaiseRate().compareTo(BigDecimal.ZERO) > 0){
							toAddInterest = toAddInterest.add(this.getProjectActivityCurrentPeriodAddInterest(packageInvestOrder.getActivityRaiseRate(), dto.getInvestOrderId(), Byte.valueOf("0")));
						}
					}
					responseDTO.setTotalRepayPriInter(responseDTO.getTotalRepayPriInter().add(toAddInterest));
				}

				List<ProjectInvestOrder> projectInvestOrderList = projectInvestOrderMapper.selectByInvestOrderIds(investOrderIds);
				for(ProjectInvestOrder projectInvestOrder : projectInvestOrderList) {
					List<RepaymentPlanDTO> repaymentPlan = RepaymentPlanContext.getRepaymentPlan(com.niiwoo.tripod.base.plan.support.RepaymentTypeEnum.enumOf(projectInvestOrder.getRepaymentType()), projectInvestOrder.getProjectType(),
							projectInvestOrder.getAmount(), projectInvestOrder.getBorrowRate(), projectInvestOrder.getDeadline(), PeriodUnitEnum.enumOf(projectInvestOrder.getDeadlineUnit()), new Date());
					for (RepaymentPlanDTO repaymentPlanDTO : repaymentPlan) {
						investInterest = investInterest.add(repaymentPlanDTO.getInterest());
					}
				}
			}

			if (PackageInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(packageInvestOrder.getEvolutionStatus())) {
				StatisticUserBillAmountRequestDTO statisticUserBillAmountRequestDTO = new StatisticUserBillAmountRequestDTO();
				List<BillAmountStatisticsEnum> billAmountStatisticsEnums = Arrays.asList(BillAmountStatisticsEnum.ACCEPTED_INTEREST,
						BillAmountStatisticsEnum.PENALTY_INTEREST,
						BillAmountStatisticsEnum.PLATFORM_AND_ACTIVITY_INCREASE_INTEREST,
						BillAmountStatisticsEnum.CARD_AND_REDPACKET_INVEST,
						BillAmountStatisticsEnum.CARD_INCREASE_INTEREST,
						BillAmountStatisticsEnum.INVEST_CASHBACK);
				statisticUserBillAmountRequestDTO.setUserId(packageInvestOrder.getUserId());
				statisticUserBillAmountRequestDTO.setInvestIds(new ArrayList<>(investOrderIds));
				statisticUserBillAmountRequestDTO.setBillAmountStatisticsEnums(billAmountStatisticsEnums);

				List<StatisticUserBillAmountReponseDTO> receivedStatistic = userBillStatisticsDubboService.statisticUserBillAmounts(statisticUserBillAmountRequestDTO);

				BigDecimal interest = BigDecimal.ZERO;
				BigDecimal penaltyFee = BigDecimal.ZERO;
				BigDecimal platformAddInterest = BigDecimal.ZERO;
				BigDecimal prizeAddInterest = BigDecimal.ZERO;
				for (StatisticUserBillAmountReponseDTO statisticUserBillAmountReponseDTO: receivedStatistic) {
					if(statisticUserBillAmountReponseDTO != null) {
						if(BillAmountStatisticsEnum.ACCEPTED_INTEREST.equals(statisticUserBillAmountReponseDTO.getBillAmountStatisticsEnum())){
							interest = statisticUserBillAmountReponseDTO.getAmount() == null ? BigDecimal.ZERO : statisticUserBillAmountReponseDTO.getAmount();
						}
						if(BillAmountStatisticsEnum.PLATFORM_AND_ACTIVITY_INCREASE_INTEREST.equals(statisticUserBillAmountReponseDTO.getBillAmountStatisticsEnum())){
							platformAddInterest = statisticUserBillAmountReponseDTO.getAmount() == null ? BigDecimal.ZERO : statisticUserBillAmountReponseDTO.getAmount();
						}
						if(BillAmountStatisticsEnum.PENALTY_INTEREST.equals(statisticUserBillAmountReponseDTO.getBillAmountStatisticsEnum())){
							penaltyFee = statisticUserBillAmountReponseDTO.getAmount() == null ? BigDecimal.ZERO : statisticUserBillAmountReponseDTO.getAmount();
						}
						if(BillAmountStatisticsEnum.CARD_INCREASE_INTEREST.equals(statisticUserBillAmountReponseDTO.getBillAmountStatisticsEnum())){
							prizeAddInterest = statisticUserBillAmountReponseDTO.getAmount() == null ? BigDecimal.ZERO : statisticUserBillAmountReponseDTO.getAmount();
						}

					}
				}

				// 参考收益：预期利息+预期加息
				responseDTO.setReferenceIncome(interest.add(penaltyFee).add(platformAddInterest).add(prizeAddInterest));
				// 已收利息
				responseDTO.setInterest(interest);
				// 已收罚息
				responseDTO.setPenaltyFee(penaltyFee);
				// 平台或活动加息
				responseDTO.setPlatformAddInterest(platformAddInterest);
				// 加息券加息
				responseDTO.setPrizeAddInterest(prizeAddInterest);
			} else if(PackageInvestOrderEvolutionStatusEnum.CLOSED.getValue().equals(packageInvestOrder.getEvolutionStatus())){
				// 参考收益：预期利息+预期加息
				responseDTO.setReferenceIncome(BigDecimal.ZERO);
				// 预期利息
				responseDTO.setInterest(BigDecimal.ZERO);
				// 预期利息
				responseDTO.setPenaltyFee(BigDecimal.ZERO);
				// 平台或活动加息
				responseDTO.setPlatformAddInterest(BigDecimal.ZERO); // 投资订单利息字段包含投资利息与平台或活动加息
				// 加息券加息
				responseDTO.setPrizeAddInterest(BigDecimal.ZERO);
			} else{
				// 参考收益：预期利息+预期加息
				responseDTO.setReferenceIncome(packageInvestOrder.getInterest().add(packageInvestOrder.getAddInterest()));
				// 预期利息
				responseDTO.setInterest(investInterest);
				// 平台或活动加息
				responseDTO.setPlatformAddInterest(packageInvestOrder.getInterest().subtract(responseDTO.getInterest())); // 投资订单利息字段包含投资利息与平台或活动加息
				// 加息券加息
				responseDTO.setPrizeAddInterest(packageInvestOrder.getAddInterest());
			}

			// 标的加息
			if (packageInvestOrder.getActivityRaiseRate() != null && packageInvestOrder.getActivityRaiseRate().compareTo(BigDecimal.ZERO) > 0 && investOrderIds.size() > 0) {
				SummarizeAmountRespDTO projectAddInterest = investOrderService.summarizeProjectAddInterestAmount(packageInvestOrder.getUserId(), new ArrayList<>(investOrderIds));
				responseDTO.setRepayAmount(responseDTO.getRepayAmount().add(projectAddInterest.getReceivedAmount()));
				if (PackageInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(packageInvestOrder.getEvolutionStatus())) {
					responseDTO.setTotalRepayPriInter(responseDTO.getTotalRepayPriInter().add(projectAddInterest.getReceivedAmount()));
				}
				if (PackageInvestOrderEvolutionStatusEnum.BACKING.getValue().equals(packageInvestOrder.getEvolutionStatus())
						|| PackageInvestOrderEvolutionStatusEnum.BACKING_OVERDUE.getValue().equals(packageInvestOrder.getEvolutionStatus())) {
					responseDTO.setTotalRepayPriInter(responseDTO.getTotalRepayPriInter().add(projectAddInterest.getToReceivedAmount()));
				}
			}
			// 投资加息劵
			if (packageInvestOrder.getPrizeId() != null && packageInvestOrder.getPrizeTypteId() != null
					&& UserPrizeTypeIdEnum.INVESTMENT_RAISE_INTEREST_RATES.getPrizeType().equals(packageInvestOrder.getPrizeTypteId())) {
				SummarizeAmountRespDTO prizeAddInterest = this.summarizePrizeAmount(packageInvestOrder.getUserId(), packageInvestOrder.getPrizeId(), packageInvestOrder.getPrizeTypteId());
				responseDTO.setRepayAmount(responseDTO.getRepayAmount().add(prizeAddInterest.getReceivedAmount()));
				if (PackageInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(packageInvestOrder.getEvolutionStatus())) {
					responseDTO.setTotalRepayPriInter(responseDTO.getTotalRepayPriInter().add(prizeAddInterest.getReceivedAmount()));
				}
				if (PackageInvestOrderEvolutionStatusEnum.BACKING.getValue().equals(packageInvestOrder.getEvolutionStatus())
						|| PackageInvestOrderEvolutionStatusEnum.BACKING_OVERDUE.getValue().equals(packageInvestOrder.getEvolutionStatus())) {
					responseDTO.setTotalRepayPriInter(responseDTO.getTotalRepayPriInter().add(prizeAddInterest.getToReceivedAmount()));
				}
			}

			if (PackageInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(packageInvestOrder.getEvolutionStatus())) {
				responseDTO.setRepayAmount(responseDTO.getAmount().add(responseDTO.getReferenceIncome()));
				responseDTO.setTotalRepayPriInter(responseDTO.getRepayAmount());
			}
		}
		return responseDTO;
	}

	/**
	 * 智能投包明细订单列表
	 *
	 * @param requestDTO
	 *            请求DTO
	 * @return PageResponseDTO<IntelligenceDetailListResponseDTO>
	 */
	public PageResponseDTO<IntelligenceDetailListResponseDTO> intelligenceDetailList(IntelligenceDetailListRequestDTO requestDTO) {
		log.info("intelligenceDetailList IntelligenceDetailListRequestDTO:{}", JSON.toJSONString(requestDTO));
		PageResponseDTO<IntelligenceDetailListResponseDTO> pageResponseDTO = new PageResponseDTO<>();
		Integer count = projectPackageInvestOrderDetailMapperExt.projectOrderCountByPackageInvestOrderId(requestDTO);
		if (count <= 0) {
			pageResponseDTO.setTotalCount(count);
			pageResponseDTO.measureTotalPage(count, requestDTO.getPageSize());
			pageResponseDTO.setItems(new ArrayList<>());
			return pageResponseDTO;
		}

		List<Long> projectIds = new ArrayList<>();
		Set<Long> investOrderIds = new HashSet<>();
		List<IntelligenceDetailListResponseDTO> responseDTOList = new ArrayList<>();
		List<ProjectInvestOrderListDTO> investOrderList = projectPackageInvestOrderDetailMapperExt.projectOrderListByPackageInvestOrderId(requestDTO);
		for (ProjectInvestOrderListDTO investOrder : investOrderList) {
			IntelligenceDetailListResponseDTO responseDTO = new IntelligenceDetailListResponseDTO();
			responseDTO.setPackageType(investOrder.getPackageType());
			responseDTO.setProjectId(investOrder.getProjectId());
			responseDTO.setOrderId(investOrder.getId());
			responseDTO.setDeadline(investOrder.getDeadline());
			responseDTO.setDeadlineUnit(investOrder.getDeadlineUnit());
			responseDTO.setBorrowRate(investOrder.getBorrowRate());
			responseDTO.setAddRate(investOrder.getActivityRaiseRate());
			responseDTO.setStatus(investOrder.getEvolutionStatus());
			responseDTO.setAmount(investOrder.getAmount());


			// 实际收益=实收利息+实收加息(回款利息+回款罚息+已收加息)
			if(ProjectInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(investOrder.getEvolutionStatus())
					|| ProjectInvestOrderEvolutionStatusEnum.TRANSFERRED.getValue().equals(investOrder.getEvolutionStatus())){
				InvestorCreditor investorCreditor = investorCreditorMapperExt.queryInvestorCreditorByInvestOrderId(investOrder.getId());
				if(ProjectInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(investOrder.getEvolutionStatus())) {
					responseDTO.setEndTime(investorCreditor.getOverTime());
				} else {
					responseDTO.setEndTime(investorCreditor.getTransferTime());
				}

				StatisticUserBillAmountRequestDTO statisticUserBillAmountRequestDTO = new StatisticUserBillAmountRequestDTO();
				List<BillAmountStatisticsEnum> billAmountStatisticsEnums = Arrays.asList(BillAmountStatisticsEnum.ACCEPTED_INTEREST,
						BillAmountStatisticsEnum.PENALTY_INTEREST,
						BillAmountStatisticsEnum.PLATFORM_AND_ACTIVITY_INCREASE_INTEREST,
						BillAmountStatisticsEnum.CARD_AND_REDPACKET_INVEST,
						BillAmountStatisticsEnum.CARD_INCREASE_INTEREST,
						BillAmountStatisticsEnum.INVEST_CASHBACK);
				statisticUserBillAmountRequestDTO.setUserId(investOrder.getUserId());
				statisticUserBillAmountRequestDTO.setInvestId(investOrder.getId());
				statisticUserBillAmountRequestDTO.setBillAmountStatisticsEnums(billAmountStatisticsEnums);

				List<StatisticUserBillAmountReponseDTO> receivedStatistic = userBillStatisticsDubboService.statisticUserBillAmounts(statisticUserBillAmountRequestDTO);

				BigDecimal interest = BigDecimal.ZERO;
				BigDecimal penaltyFee = BigDecimal.ZERO;
				BigDecimal platformAddInterest = BigDecimal.ZERO;
				BigDecimal prizeAddInterest = BigDecimal.ZERO;
				for (StatisticUserBillAmountReponseDTO statisticUserBillAmountReponseDTO: receivedStatistic) {
					if(statisticUserBillAmountReponseDTO != null) {
						if(BillAmountStatisticsEnum.ACCEPTED_INTEREST.equals(statisticUserBillAmountReponseDTO.getBillAmountStatisticsEnum())){
							interest = statisticUserBillAmountReponseDTO.getAmount() == null ? BigDecimal.ZERO : statisticUserBillAmountReponseDTO.getAmount();
						}
						if(BillAmountStatisticsEnum.PLATFORM_AND_ACTIVITY_INCREASE_INTEREST.equals(statisticUserBillAmountReponseDTO.getBillAmountStatisticsEnum())){
							platformAddInterest = statisticUserBillAmountReponseDTO.getAmount() == null ? BigDecimal.ZERO : statisticUserBillAmountReponseDTO.getAmount();
						}
						if(BillAmountStatisticsEnum.PENALTY_INTEREST.equals(statisticUserBillAmountReponseDTO.getBillAmountStatisticsEnum())){
							penaltyFee = statisticUserBillAmountReponseDTO.getAmount() == null ? BigDecimal.ZERO : statisticUserBillAmountReponseDTO.getAmount();
						}
						if(BillAmountStatisticsEnum.CARD_INCREASE_INTEREST.equals(statisticUserBillAmountReponseDTO.getBillAmountStatisticsEnum())){
							prizeAddInterest = statisticUserBillAmountReponseDTO.getAmount() == null ? BigDecimal.ZERO : statisticUserBillAmountReponseDTO.getAmount();
						}

					}
				}

				// 已挣收益：预期利息+预期加息
				responseDTO.setInterest(interest.add(penaltyFee).add(platformAddInterest).add(prizeAddInterest));
			} else if(ProjectInvestOrderEvolutionStatusEnum.CLOSED.getValue().equals(investOrder.getEvolutionStatus())){
				responseDTO.setInterest(BigDecimal.ZERO);
				responseDTO.setEndTime(investOrder.getExpireTime().before(investOrder.getUpdateTime()) ?  investOrder.getExpireTime() : investOrder.getUpdateTime());
			} else {
				// 参考收益：参考收益=参考利息+参考活动加息（不含红包和加息券）
				responseDTO.setInterest(investOrder.getInterest().add(investOrder.getAddInterest()));
			}
			investOrderIds.add(investOrder.getId());
			projectIds.add(investOrder.getProjectId());
			responseDTOList.add(responseDTO);
		}

		if (investOrderIds.size() > 0) {
			List<InvestorCreditor> investorCreditorList = investorCreditorMapperExt.selectByInvestOrderIds(investOrderIds);
			investorCreditorList.forEach(investorCreditor -> responseDTOList.forEach(responseDTO -> {
				if(investorCreditor.getExpectOverDate() != null && investorCreditor.getInvestOrderId().equals(responseDTO.getOrderId())){
					responseDTO.setExpireTime(investorCreditor.getExpectOverDate()); // 到期日期
				}
			}));
		}

		if(projectIds.size() > 0){
            Set<String> borrowCompanyUserIds = new HashSet<>();
            Set<String> borrowPersonalUserIds = new HashSet<>();
            List<Project> projects = projectMapperExt.queryProjectListByProjectIds(projectIds);
            projects.forEach(project -> responseDTOList.forEach(responseDTO -> {
                if (responseDTO.getProjectId().equals(project.getProjectId())) {
                    responseDTO.setBorrowUserId(project.getBorrowUserId());
                    responseDTO.setCalInterTime(project.getFullSuccessTime()); // 计息日期

					// 已提前结清
					if (Integer.valueOf(ProjectSubStatusEnum.FINISH_ADVANCE.getSubStatus()).equals(project.getSubStatus())
							&& ProjectInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(responseDTO.getStatus())) {
						responseDTO.setStatus(Byte.valueOf("8"));
					}

                    // 逾期提示文案
                    if (ProjectInvestOrderEvolutionStatusEnum.BACKING_OVERDUE.getValue().equals(responseDTO.getStatus()) && project.getAdvanceOverdueDays() != null) {
                        if (project.getAdvanceOverdueDays() == 0) {
                            responseDTO.setOverdueMsg("担保公司将在24小时内代偿当期本息");
                        } else {
                            responseDTO.setOverdueMsg("若借款人逾期" + project.getAdvanceOverdueDays() + "天，担保公司将在第" + (project.getAdvanceOverdueDays() + 1) + "天代偿当期本息");
                        }
                    }
                    // 头像昵称设置
                    if (BorrowerTypeEnum.PERSONAL.getType().equals(project.getBorrowerType())) {
                        responseDTO.setIsEnterpriseProject(false);
                        borrowPersonalUserIds.add(project.getBorrowUserId());
                    } else {
                        responseDTO.setIsEnterpriseProject(true);
                        borrowCompanyUserIds.add(project.getBorrowUserId());
                    }
                }
            }));

            // 个人头像昵称设置
            if (borrowPersonalUserIds.size() > 0) {
                List<UserBasicInfoDTO> userBasicInfoDTOList = userBasicInfoDubboService.queryListByUserIdSet(borrowPersonalUserIds);
                userBasicInfoDTOList.forEach(userBasicInfo -> responseDTOList.forEach(responseDTO -> {
                    if (userBasicInfo.getUserId().equals(responseDTO.getBorrowUserId())) {
                        responseDTO.setNickName(userBasicInfo.getNickName());
                        responseDTO.setHeadImg(userBasicInfo.getHeadImage());
                    }
                }));
            }
            // 企业头像昵称设置
            if (borrowCompanyUserIds.size() > 0) {
                List<SimpleOrgInfo> orgInfoList = organizationDubboService.queryListByOrgIdSet(borrowCompanyUserIds);
                orgInfoList.forEach(orgInfo -> responseDTOList.forEach(responseDTO -> {
                    if (orgInfo.getId().equals(responseDTO.getBorrowUserId())) {
                        responseDTO.setHeadImg(orgInfo.getLogo());
                        responseDTO.setNickName(maskCompanyName(orgInfo.getOrganizationName()));
                    }
                }));
            }
        }

		pageResponseDTO.setTotalCount(count);
		pageResponseDTO.measureTotalPage(count, requestDTO.getPageSize());
		pageResponseDTO.setItems(responseDTOList);
		return pageResponseDTO;
	}

	/**
	 * 公司名称打码
	 */
	private static String maskCompanyName(String companyName) {
		if (StringUtils.isBlank(companyName) || companyName.length() <= 4) {
			return companyName;
		}
		return companyName.substring(0, 2) + "***" + companyName.substring(companyName.length() - 2, companyName.length());
	}

	public List<ProjectPackageInvestOrder> getIntelligenOrderList(ProjectInvestOrderPageRequest request) {
		return projectPackageInvestOrderMapperExt.getIntelligenOrderList(request);
	}

	public Integer countInvested(Long packageId) {
		return projectPackageInvestOrderMapperExt.countInvested(packageId);
	}

	// 加息券/投资返现红包
	public SummarizeAmountRespDTO summarizePrizeAmount(String userId, Long prizeId, Byte prizeTypeId) {
		log.info("summarizePrizeAmount userId={}, prizeId={}, prizeTypeId={}", userId, prizeId, prizeTypeId);
		List<Long> prizeIdList = new ArrayList<>();
		prizeIdList.add(prizeId);

		SummarizePrizeAmountReqDTO reqDTO = new SummarizePrizeAmountReqDTO();
		reqDTO.setUserId(userId);
		reqDTO.setPrizeTypeId(prizeTypeId);
		reqDTO.setPrizeIdList(prizeIdList);
		SummarizeAmountRespDTO respDTO = activityPrizeDubboService.summarizePrizeAmount(reqDTO);
		log.info("getProjectActivityAddInterest respDTO={}", JSON.toJSONString(respDTO));
		return respDTO;
	}

	// 根据状态统计标/包加息
	public BigDecimal getProjectActivityCurrentPeriodAddInterest(BigDecimal activityRaiseRate, Long investOrderId, Byte status) {
		log.info("getProjectActivityCurrentPeriodAddInterest,activityRaiseRate={},investOrderId={}", activityRaiseRate, investOrderId);
		BigDecimal addInterest = BigDecimal.ZERO;
		// 投资加息券 回款状态 0：未回款 1：已作废 2：已回款
		if (investOrderId != null && status != null && activityRaiseRate != null && activityRaiseRate.compareTo(BigDecimal.ZERO) > 0) {
			List<InvestorExtraDetailDTO> investorExtraDetailDTOList = activityPrizeDubboService.getProjectAddInterest(investOrderId);
			log.info("getProjectActivityCurrentPeriodAddInterest:investorExtraDetailDTOList={}", JSON.toJSON(investorExtraDetailDTOList));
			if (investorExtraDetailDTOList != null) {
				for (InvestorExtraDetailDTO investorExtraDetailDTO : investorExtraDetailDTOList) {
					if (investorExtraDetailDTO != null && status.equals(investorExtraDetailDTO.getStatus())) {
						addInterest = addInterest.add(investorExtraDetailDTO.getExtraAmount());
					}
				}
			}
		}
		log.info("getProjectActivityCurrentPeriodAddInterest:addInterest={}", addInterest);
		return addInterest;
	}

	// 根据状态统计投资加息劵
	public BigDecimal getPrizeCurrentPeriodAddInterest(Long prizeId, Long projectId, Byte status) {
		log.info("getPrizeCurrentPeriodAddInterest:projectInvestOrder={},status={}", prizeId, status);
		BigDecimal addInterest = BigDecimal.ZERO;
		// 投资加息券 回款状态 0：未回款 1：已作废 2：已回款
		if (prizeId != null && projectId != null && status != null) {
			List<InvestorExtraDetailDTO> investorExtraDetailDTOList = activityPrizeDubboService.getInvestorExtralDtlSingle(prizeId);
			log.info("getPrizeCurrentPeriodAddInterest:investorExtraDetailDTOList={}", JSON.toJSON(investorExtraDetailDTOList));
			if (investorExtraDetailDTOList != null) {
				for (InvestorExtraDetailDTO investorExtraDetailDTO : investorExtraDetailDTOList) {
					if (investorExtraDetailDTO != null && projectId.equals(investorExtraDetailDTO.getProjectId()) && status.equals(investorExtraDetailDTO.getStatus())) {
						addInterest = addInterest.add(investorExtraDetailDTO.getExtraAmount());
					}
				}
			}
		}
		log.info("getPrizeCurrentPeriodAddInterest:addInterest={}", addInterest);
		return addInterest;
	}

	/**
	 * 查询我的智能投订单的最大最小日期
	 *
	 * @param userId
	 *            用户ID
	 * @param type
	 *            投资类型
	 * @return InvestOrderMaxandMinDateResponseDTO
	 */
	public InvestOrderMaxandMinDateResponseDTO getMyIntelligenceInvestOrderMaxAndMinDate(String userId, Byte type) {
		InvestOrderMaxandMinDateResponseDTO responseDTO = null;
		IntelligenceInvestOrderMaxAndMinDateDTO maxAndMinDate = projectPackageInvestOrderMapperExt.getMyIntelligenceInvestOrderMaxAndMinDate(userId, type);
		if (maxAndMinDate != null) {
			responseDTO = new InvestOrderMaxandMinDateResponseDTO();
			responseDTO.setMaxTime(maxAndMinDate.getMaxTime());
			responseDTO.setMinTime(maxAndMinDate.getMinTime());
		}
		return responseDTO;
	}

	/**
	 * 增加智能投订单
	 * 
	 * @param request
	 * @return
	 */
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public ProjectPackageInvestOrder generatePackageInvestOrder(IntelligenceInvestDubboRequest request,ProjectPackage projectPackage) {
		ProjectPackageInvestOrder order = new ProjectPackageInvestOrder();
		order.setActivityRaiseRate(projectPackage.getActivityRaiseRate());
		order.setAddInterest(BigDecimal.ZERO);
		order.setAddRate(BigDecimal.ZERO);
		order.setAmount(request.getInvestAmount());
		order.setBorrowRate(projectPackage.getBorrowRate());
		order.setCreateTime(new Date());
		order.setDeadline(projectPackage.getDeadline());
		order.setDeadlineUnit(projectPackage.getDeadlineUnit());
		order.setErrorTime(0);
		order.setEvolutionStatus(PackageInvestOrderEvolutionStatusEnum.DEALING.getValue());
		order.setId(snowflakeIdWorker.nextId());
		order.setInterest(BigDecimal.ZERO);
		order.setInvestorType(request.getInvestUserType());
		order.setInvestTime(new Date());
		order.setPackageId(projectPackage.getPackageId());
		order.setPackageType(projectPackage.getPackageType());
		order.setPrizeId(request.getPrizeId());
		order.setProjectNum(0);
		order.setRealInvestAmount(BigDecimal.ZERO);
		order.setRepaymentType(projectPackage.getRepaymentType());
		order.setStatus(PackageProjectInvestOrderStatusEnum.PENDING_PAYMENT.getValue());
		order.setTitle(projectPackage.getTitle());
		order.setUpdateTime(new Date());
		order.setUserId(request.getUserId());
		projectPackageInvestOrderMapperExt.insertSelective(order);
		return order;
	}
	@Transactional(propagation=Propagation.REQUIRES_NEW)
	public void changeOrderFalse(ProjectPackageInvestOrder investOrder) {
		ProjectPackageInvestOrder order = new ProjectPackageInvestOrder();
		order.setId(investOrder.getId());
		order.setUpdateTime(new Date());
		order.setStatus(PackageProjectInvestOrderStatusEnum.CANCEL.getValue());
		order.setEvolutionStatus(PackageInvestOrderEvolutionStatusEnum.CLOSED.getValue());
		order.setCloseTime(new Date());
		projectPackageInvestOrderMapperExt.updateByPrimaryKeySelective(order);
	}
	/**
	 * 解冻资金生成记录
	 * 
	 * @param request
	 */
	@Transactional(isolation = READ_COMMITTED,propagation=Propagation.REQUIRES_NEW)
	public InvestAmountUnfreeze unfreezeAmountInsert(IntelligenceUnfreezeDTO request) {
		InvestAmountUnfreeze investAmountUnfreeze = investAmountUnfreezeMapper.selectByPrimaryKey(request.getProjectPackageInvestOrderId());
		if (investAmountUnfreeze == null) {
			investAmountUnfreeze = new InvestAmountUnfreeze();
			investAmountUnfreeze.setAmount(request.getAmount());
			investAmountUnfreeze.setCreateTime(new Date());
			investAmountUnfreeze.setId(request.getProjectPackageInvestOrderId());
			investAmountUnfreeze.setStatus(Byte.valueOf("0"));
			investAmountUnfreeze.setUpdateTime(new Date());
			investAmountUnfreeze.setUserId(request.getUserId());
			investAmountUnfreezeMapper.insertSelective(investAmountUnfreeze);
		}
		return investAmountUnfreeze;
	}

	@Transactional
	public void unfreezeAmountsuccess(Long projectPackageInvestOrderId) {
		InvestAmountUnfreeze investAmountUnfreeze = new InvestAmountUnfreeze();
		investAmountUnfreeze.setId(projectPackageInvestOrderId);
		investAmountUnfreeze.setStatus(Byte.valueOf("1"));
		investAmountUnfreeze.setUpdateTime(new Date());
		investAmountUnfreezeMapper.updateByPrimaryKeySelective(investAmountUnfreeze);
	}
	 
	public InvestAmountUnfreeze findUnFree(Long packInvestOrderId) {
		return investAmountUnfreezeMapper.selectByPrimaryKey(packInvestOrderId);
	}
	/**
	 * 根据子订单获取智能投投资订单数据
	 * @param subInvestId
	 * @return
	 */
	public ProjectPackageInvestOrderDTO getProjectPackageInvestOrderBySubInvestOrderId(Long subInvestId) {
		ProjectPackageInvestOrderDetail detail =projectPackageInvestOrderDetailMapperExt.selectByInvestOrderId(subInvestId);
		if(Objects.isNull(detail)) {
			return null;
		}
		ProjectPackageInvestOrder order =projectPackageInvestOrderMapperExt.selectByPrimaryKey(detail.getPackageInvestOrderId());
		if(Objects.isNull(order)) {
			return null;
		}
		ProjectPackageInvestOrderDTO result = new ProjectPackageInvestOrderDTO();
		BeanUtils.copyProperties(order, result);
		return result;
	}
}
